﻿/*=============================================================================
* File Name : Plane.h                         Ver : 1.00  Date : 2009-3-26
*
* Description :
*
*       平面クラスB　ヘッダ
*
* Author : 土田　悠貴.
*============================================================================*/
#ifndef _PLANE_H_
#define _PLANE_H_

#include "../math/Vector3.h"

namespace tglib
{

class Matrix3;
class Matrix4;

/**
 * @brief 平面クラス
 */
class Plane
{
public:
	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 */
	Plane();

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     A　面法線ｘ成分．
	 * @param [in]     B　面法線ｙ成分．
	 * @param [in]     C　面法線ｚ成分．
	 * @param [in]     D　原点からの距離．
	 */
	Plane( float A, float B, float C, float D );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     N　法線ベクトル．
	 * @param [in]     D　原点からの距離．
	 */
	Plane( const Vector3& N, float D );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     P　平面上の座標．
	 * @param [in]     N　法線ベクトル．
	 */
	Plane( const Vector3& P, const Vector3& N );

	/*===========================================================================*/
	/**
	 * コンストラクタ．
	 *
	 * @param [in]     V1 座標1.
	 * @param [in]     V2 座標2.
	 * @param [in]     V3 座標3.
	 */
	Plane( const Vector3& V1, const Vector3& V2, const Vector3& V3 );

	/*===========================================================================*/
	/**
	 * 正規化．
	 *
	 * @return 正規化した平面
	 */
	Plane& normalize();

	/*===========================================================================*/
	/**
	 * 正規化後の平面を得る．
	 *
	 * @return 正規化した平面
	 */
	Plane getNormalize();

	/*===========================================================================*/
	/**
	 * 平面上の位置を取得．
	 *
	 * @return 平面上の座標
	 */
	Vector3 getPoint() const;

	/*===========================================================================*/
	/**
	 * 平面とベクトルの内積を求める．
	 *
	 * @param [in]   v 3Dベクトル.
	 * @return 内積.
	 */
	float dot( const Vector3& v ) const;

	/*===========================================================================*/
	/**
	 * 平面と点の距離を求める．
	 *
	 * @param [in]   v 点座標.
	 * @return 距離.
	 */
	float distance( const Vector3& v ) const;

	/*===========================================================================*/
	/**
	 * 平面と線分が交差するか調べる．
	 *
	 * @param [in]   Line0 始点座標.
	 * @param [in]   Line1 終点座標.
	 * @return 交差しているならtrue, そうでないならfalse.
	 */
	bool isIntersectLine( const Vector3& line0, const Vector3& line1 ) const;

	/*===========================================================================*/
	/**
	 * 平面と線分の交点を取得する．
	 *
	 * @param [in]   line0 始点座標.
	 * @param [in]   line1 終点座標.
	 * @return 交差している座標.
	 */
	Vector3 getIntersectLine( const Vector3& line0, const Vector3& line1 ) const;

	/*===========================================================================*/
	/**
	 * 平面とレイが交差するか調べる．
	 *
	 * @param [in]   rayPos レイの始点.
	 * @param [in]   rayDir レイの方向.
	 * @return 交差しているならtrue, そうでないならfalse.
	 */
	bool isIntersectRay( const Vector3& rayPos, const Vector3& rayDir ) const;

	/*===========================================================================*/
	/**
	 * 平面とレイの交点を取得する．
	 *
	 * @param [in]   ray レイの始点.
	 * @param [in]   dir レイの方向.
	 * @return 交差しているならtrue, そうでないならfalse.
	 */
	Vector3 getIntersectRay( const Vector3& ray, const Vector3& dir ) const;

public:
	/**
	 * @brief 位置関係列挙型
	 */
	enum PlanePosition
	{
		FRONT_PLANE = 0,	 /**< 平面の前 */
		BEHIND_PLANE = 1,	 /**< 平面の後ろ */
		ON_PLANE = 2,		 /**< 平面上 */
		INTERSECTS_PLANE = 3 /**< 平面と交差	*/
	};

public:
	/*===========================================================================*/
	/**
	 * 平面と座標の位置関係を返す．
	 *
	 * @param [in]   pos 調べる座標.
	 * @return 位置関係.
	 */
	PlanePosition getClassifyPoint( const Vector3& pos ) const;

	/*===========================================================================*/
	/**
	 * 平面と球体の位置関係を返す．
	 *
	 * @param [in]   center 中心座標.
	 * @param [in]   radius 半径.
	 * @return 位置関係.
	 */
	PlanePosition getClassifyShpere( const Vector3& center, float radius ) const;

	/*===========================================================================*/
	/**
	 * 平面上の座標と平面の法線ベクトルから平面を作成．
	 *
	 * @param [in]   point 平面上の座標.
	 * @param [in]   normal 平面の法線ベクトル.
	 * @return 平面データ.
	 */
	Plane fromPointNrmal( const Vector3& point, const Vector3& normal );

	/*===========================================================================*/
	/**
	 * 平面上の座標と平面の法線ベクトルから平面を作成．
	 *
	 * @param [in]   point1 平面構成する座標1.
	 * @param [in]   point2 平面構成する座標2.
	 * @param [in]   point3 平面構成する座標3.
	 * @return 平面データ.
	 */
	Plane fromPoints( const Vector3& point1, const Vector3& point2, const Vector3& point3 );

	/*===========================================================================*/
	/**
	 * (+)単項演算子オーバーロード．
	 *
	 * @return 結果のPlane．
	 */
	Plane operator + () const;

	/*===========================================================================*/
	/**
	 * (-)単項演算子オーバーロード．
	 *
	 * @return 結果のPlane．
	 */
	Plane operator - () const;

public:
	/** @brief  面法線ｘ成分 */
	float		a;

	/** @brief 面法線ｙ成分 */
	float		b;

	/** @brief 面法線ｚ成分 */
	float		c;

	/** @brief 原点からの距離 */
	float		d;


};

/***  以下非メンバ関数 *******************************************************/

/*===========================================================================*/
/**
 * (==) 演算子オーバーロード．
 *
 * @param [in]  Plane1 Plane．
 * @param [in]  Plane2 Plane．
 * @return 比較結果．
 */
bool operator == ( const Plane& plane1, const Plane& plane2 );

/*===========================================================================*/
/**
 * (!=) 演算子オーバーロード．
 *
 * @param [in]  Plane1 Plane．
 * @param [in]  Plane2 Plane．
 * @return 比較結果．
 */
bool operator != ( const Plane& plane1, const Plane& plane2 );

} // namespace tglib

#endif
/*========= End of File =====================================================*/
